package com.szmirren.vxApi.spi.handler.impl;

import io.vertx.core.http.HttpServerRequest;
import io.vertx.core.json.JsonObject;
import io.vertx.ext.web.RoutingContext;

import java.security.MessageDigest;

import com.microsoft.sqlserver.jdbc.StringUtils;
import com.szmirren.vxApi.core.common.VxApiRequestBodyHandler;
import com.szmirren.vxApi.core.entity.VxApiContentType;
import com.szmirren.vxApi.core.entity.VxApis;
import com.szmirren.vxApi.core.enums.ContentTypeEnum;
import com.szmirren.vxApi.core.handler.route.VxApiRouteConstant;
import com.szmirren.vxApi.spi.common.HttpHeaderConstant;
import com.szmirren.vxApi.spi.handler.VxApiBeforeHandler;

/**
 * 前置处理器处理示例
 * 
 * @author <a href="http://szmirren.com">Mirren</a>
 *
 */
public class SignBeforeHandler implements VxApiBeforeHandler {
	private VxApis apis;
    private ContentTypeEnum signFailContentType;
    private String signFailResult;
    
	@Override
	public void handle(RoutingContext rct) {
		// 这里做些什么事情后将请求放行到下一个处理器,或者在这里响应请求
	    String sign = rct.request().params().get("sign");
	    
	    // 解析用户请求的主体
        HttpServerRequest rctRequest = rct.request();	    
        VxApiRequestBodyHandler bodyHandler = new VxApiRequestBodyHandler(loadContentType(rctRequest), 0);
        rctRequest.handler(body -> {
            if (!bodyHandler.isExceededMaxLen()) {
                bodyHandler.handle(body);
            }
        });
        rctRequest.endHandler(end -> {
            String body = bodyHandler.getBodyString();
            
            JsonObject json = apis.getBeforeHandlerOptions().getOption();
            String md5 = MD5(json.getString("key")+"="+json.getString("secret")+"&body=" + body);
            if (!StringUtils.isEmpty(sign) && sign.equalsIgnoreCase(md5)) {
                rct.put("VxApiBodyDATA",body);
                rct.next();
            }
            else {
                rct.response().putHeader(HttpHeaderConstant.CONTENT_TYPE, signFailContentType.val()).end(signFailResult);
            }
        });
	}

	public SignBeforeHandler(VxApis api) {
		super();
		this.apis = api;
		
		JsonObject json = apis.getBeforeHandlerOptions().getOption();
		String type = json.getString("signFailContentType");
		if (!StringUtils.isEmpty(type)) signFailContentType = ContentTypeEnum.valueOf(type);
		else signFailContentType = ContentTypeEnum.JSON_UTF8;
		String fail = json.getString("signFailResult");
        if (!StringUtils.isEmpty(fail)) signFailResult = fail;
        else signFailResult = "Invalid signature";
	}

    /**
     * 加载Content-Type类型
     * 
     * @param request
     * @return
     */
    private VxApiContentType loadContentType(HttpServerRequest request) {
        String contentType = request.headers().get(VxApiRouteConstant.CONTENT_TYPE);
        if (contentType == null) {
            if (request.headers().get(VxApiRouteConstant.CONTENT_TYPE.toLowerCase()) == null) {
                return new VxApiContentType(null);
            } else {
                contentType = request.headers().get(VxApiRouteConstant.CONTENT_TYPE.toLowerCase());
            }
        }
        return new VxApiContentType(contentType);
    }
    
    private String MD5(String s)
    {
        byte[] btInput = s.getBytes();
        
        return MD5(btInput);
    }

    /**
     * byte[]数组 MD5成字符串
     * 
     * @param btInput
     *            byte[]数组
     * @return 字符串
     */
    private String MD5(byte[] btInput)
    {
        char hexDigits[] =
        {
                '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
        };
        
        try
        {
            MessageDigest mdInst = MessageDigest.getInstance("MD5");
            
            mdInst.update(btInput);
            byte[] md = mdInst.digest();
            int j = md.length;
            char str[] = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++)
            {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        }
        catch (Exception e)
        {
            e.printStackTrace();
            return null;
        }
    }    
}
